// 导入 mysql 包
const mysql = require("mysql");

// 将回调函数封装为 Promise 方式
class MySql {
  // 构造函数
  constructor(config) {
    // 产生数据库连接池对象： pool
    this.pool = mysql.createPool(config);
  }
  /**
   * query
   * 执行 SQL 语句并返回结果
   *
   * @param {string} sql 语句
   * @param {Array<any>} values 参数数组
   * @returns {Promise<Array>}
   */
  async query(sql, ...values) {
    // 兼容使用ES6的标签模板
    if (Array.isArray(sql))
      sql = String.raw({ raw: sql }, ...new Array(values.length).fill("?"));
    else [values] = values;
    // 封装 mysql.pool.query 成 Promise 对象
    return new Promise((resolve, reject) => {
      this.pool.query(sql, values, (error, results, fields) => {
        if (error) return reject(error);
        resolve([results, fields]);
      });
    });
  }
  /**
   * select
   * 适合执行 SELECT SQL 语句，返回查询结果。
   *
   * @param {string} sql select 语句
   * @param {array} values 参数数组
   * @returns {Promise<Array<any>>} 查询结果数组
   */
  async select(sql, ...values) {
    const [results] = await this.query(sql, ...values);
    return results;
  }
  /**
   * insert 执行 Insert SQL 语句，返回插入语句的 id。
   * @param {string} sql insert 语句
   * @param {Array<any>} values 参数数组
   * @returns {Promise<number>} 插入语句的 id
   */
  async insert(sql, ...values) {
    const [results] = await this.query(sql, ...values);
    return results.insertId;
  }
  /**
   * findOne
   * 只返回一条记录，适合执行聚合的语句。
   *
   * @param {string} sql select 语句
   * @param {Array} values 参数数组
   * @returns {Promise<any>} 返回一条记录
   */
  async findOne(sql, ...values) {
    const [[one]] = await this.query(sql, ...values);
    return one;
  }
  /**
   * close
   * 关闭连接池对象
   *
   * @returns {void}
   */
  async close() {
    return new Promise((resolve, reject) => {
      this.pool.end((err) => {
        if (err) return reject(err);
        resolve();
      });
    });
  }
}
const { DATABASE_URL = "mysql://root:sql2019@localhost/todos" } = process.env;

const db = new MySql(DATABASE_URL);

module.exports = { db };

